package com.grm.task.manager.service;

import com.grm.task.manager.common.Result;
import com.grm.task.manager.entity.Task;
import com.grm.task.manager.enums.TaskStatusEnum;
import com.grm.task.manager.enums.TaskTypeEnum;
import com.grm.task.manager.mapper.TaskMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.ListUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class TaskService {
    @Autowired
    private TaskMapper taskMapper;
    @Autowired
    private RedissonClient redissonClient;

    // 添加任务
    public Result addTasks(List<Task> tasks) {
        if (ObjectUtils.isEmpty(tasks)) {
            return Result.failed("没有选择可提交的任务！");
        }
        RLock fairLock = redissonClient.getFairLock("taskFairLock");
        fairLock.lock();
        try {
            // 1. 从数据库查询，是否包含已有任务
            List<String> taskNames = tasks.stream().map(Task::getName).collect(Collectors.toList());
            List<Task> hadTasks = taskMapper.queryTasksByNames(taskNames);
            // 2. 如果包含已有任务，抛出业务异常
            if (!ObjectUtils.isEmpty(hadTasks)) {
                return Result.failed("任务已存在，请不要重复提交！");
            }
            // 3. 查询此用户所在的队列运行数
            Integer taskType = queryTaskTypeByUsername("admin");
            if (taskType == TaskTypeEnum.UNKNOWN.getTaskType()) {
                return Result.failed("用户不在高、中、低队列池中，请检查！");
            }
            // 4. 指定每一个任务的orderNum，以供后续插队使用
            Long maxOrderNum = taskMapper.queryMaxOrderNumByType(taskType);
            for (int i = 0; i < tasks.size(); i++) {
                Task task = tasks.get(i);
                task.setOrderNum(maxOrderNum+1+i);
            }

            List<Task> runningTasks =
                taskMapper.queryTasksByStatusAndType(TaskStatusEnum.RUNNING.getStatus(), taskType);
            int maxJobCount = TaskTypeEnum.queryMaxJobCountByTaskType(taskType);
            // 可以支持的排队数(差值),maxJobCount一定>=runningTasks.size()
            int dValue = maxJobCount - runningTasks.size();
            if (dValue <= 0) { // 没有资源了，全部等待
                taskMapper.batchInsertTasksAndSetStatus(tasks, TaskStatusEnum.WAITING.getStatus());
            } else { // 有资源
                if (dValue >= tasks.size()) { // 资源比提交的任务多
                    // 全部可以直接提交运行
                    taskMapper.batchInsertTasksAndSetStatus(tasks, TaskStatusEnum.RUNNING.getStatus());
                } else { // 资源比提交的任务少，但也有资源， 一部分直接运行，一部分排队等待
                    List<List<Task>> partitionTasks = ListUtils.partition(tasks, dValue);
                    List<Task> insertRunningTasks = partitionTasks.get(0);
                    List<Task> insertWaitingTasks = partitionTasks.get(1);
                    taskMapper.batchInsertTasksAndSetStatus(insertRunningTasks, TaskStatusEnum.RUNNING.getStatus());
                    taskMapper.batchInsertTasksAndSetStatus(insertWaitingTasks, TaskStatusEnum.WAITING.getStatus());
                }
            }
        } catch (Exception e) {
            log.error("add task error:{}", e);
            return Result.failed("add task error:" + e.getMessage());
        } finally {
            fairLock.unlock();
        }
        return Result.success();
    }

    private Integer queryTaskTypeByUsername(String username) {
        // 1. 高 2. 中 3.低
        return TaskTypeEnum.MIDDLE.getTaskType();
    }

    public Result jumpQueue(Task task) {
        RLock fairLock = redissonClient.getFairLock("taskFairLock");
        fairLock.lock();
        try {
            // 1、判断当前任务是不是等待中，不是则抛异常、不能插队
            if(!task.getStatus().equals(TaskStatusEnum.WAITING.getStatus())){
                return Result.failed("只有等待中的任务才能插队");
            }
            // 2、获取用户所在的队列
            Integer taskType = queryTaskTypeByUsername("admin");
            if (taskType == TaskTypeEnum.UNKNOWN.getTaskType()) {
                return Result.failed("用户不在高、中、低队列池中，请检查！");
            }
            // 3、获取到最后一个运行的任务
            Task lastedRunningTask = taskMapper.queryLastedRunningTask(taskType,TaskStatusEnum.RUNNING.getStatus());
            if(task.getOrderNum().equals(lastedRunningTask.getOrderNum()+1)){
                return Result.failed("下一个执行的就是本任务，请耐心等待！");
            }
            // 4、把等待中的，小于当前任务的order_num后移 aa
            taskMapper.incrementOrderNum(TaskStatusEnum.RUNNING.getStatus(), task.getOrderNum());
            // 5、把当前task插入到这个任务后面（lastedRunningTask.orderNum+1）
            taskMapper.updateTaskOrderNum(task.getId(),lastedRunningTask.getOrderNum()+1);
        } catch (Exception e) {
            log.error("task jumpQueue error:{}", e);
            return Result.failed("task jumpQueue error:" + e.getMessage());
        } finally {
            fairLock.unlock();
        }
        return Result.success();
    }
}

